

lib s = <string.ssz>;
lib consts = <consts.ssz>;
lib se = <alpha/sdlevent.ssz>;
lib sdl = <alpha/sdlplugin.ssz>;
lib m = <math.ssz>;
lib sff = "sff.ssz";
lib bg = "bg.ssz";
lib cmd = "command.ssz";
lib fnt = "font.ssz";
lib com = "common.ssz";
lib cfg = "config.ssz";
lib snd = "sound.ssz";
lib chr = "char.ssz";
lib lua = <alpha/lua.ssz>;
lib sys = "system.ssz";
lib sc = "script.ssz";


^/char listenPort = "7500";

public &sys.System syst;


public &TextImg
{
  ^/char text;
  ^&.fnt.Font fnt;
  int bank = 0, align = 0;
  float x = 0.0, y = 0.0;
  float xscl = 1.0, yscl = 1.0;
  public void setFont(^&.fnt.Font fo)
  {
    `fnt = fo;
  }
  public void draw()
  {
    if(.se.fskip || #`fnt == 0) ret;
    `fnt~drawText(`x, `y, `xscl, `yscl, `bank, `align, `text);
  }
  public void setText(^/char t)
  {
    `text = t;
  }
  public void setBank(int b)
  {
    `bank = b;
  }
  public void setAlign(int a)
  {
    `align = a;
  }
  public void setPos(float x, float y)
  {
    `x = x;
    `y = y;
  }
  public void setScale(float x, float y)
  {
    `xscl = x;
    `yscl = y;
  }
}
void textImgNew(&.lua.State L=, int re=)
{
  re = 1;
  ^&.TextImg textImg.new(1);
  L.pushRef(textImg);
}
void textImgSetFont(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.TextImg textImg = .sc.refArg!&.TextImg?(L=, re=, argc=, nret);
  if(re < 0) ret;
  ^&.sc.Font font = .sc.refArg!&.sc.Font?(L=, re=, argc=, nret);
  if(re < 0) ret;
  textImg~setFont(font~getFont());
}
void textImgSetBank(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.TextImg textImg = .sc.refArg!&.TextImg?(L=, re=, argc=, nret);
  if(re < 0) ret;
  int b = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  textImg~setBank(b);
}
void textImgSetAlign(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.TextImg textImg = .sc.refArg!&.TextImg?(L=, re=, argc=, nret);
  if(re < 0) ret;
  int a = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  textImg~setAlign(a);
}
void textImgSetText(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.TextImg textImg = .sc.refArg!&.TextImg?(L=, re=, argc=, nret);
  if(re < 0) ret;
  ^/char text = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  textImg~setText(text);
}
void textImgSetPos(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.TextImg textImg = .sc.refArg!&.TextImg?(L=, re=, argc=, nret);
  if(re < 0) ret;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  textImg~setPos(x, y);
}
void textImgSetScale(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.TextImg textImg = .sc.refArg!&.TextImg?(L=, re=, argc=, nret);
  if(re < 0) ret;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  textImg~setScale(x, y);
}
void textImgDraw(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.TextImg textImg = .sc.refArg!&.TextImg?(L=, re=, argc=, nret);
  if(re < 0) ret;
  textImg~draw();
}


public &Anim
{
  ^&.sff.Anim!&.bg.Frame? ani;
  &.sdl.Rect window;
  float x = 0.0, y = 0.0;
  float xscl = 1.0, yscl = 1.0;
  new()
  {
    `ani.new(1);
    `ani~mask = 0;
    `window = .com.scrrect;
  }
  public void setSff(^&.sff.Sff sf)
  {
    `ani~sff = sf;
  }
  public bool setAction(^/char str)
  {
    ^^/char lines = .s.splitLines(str);
    index i = 0;
    &.bg.Action act;
    act.read(lines, i=);
    `ani~reset();
    `ani~setFrames(act.frames, act.loopstart);
    ret #act.frames > 0;
  }
  public int animTime()
  {
    ret `ani~animTime();
  }
  public void update()
  {
    `ani~action();
  }
  public void draw()
  {
    if(.se.fskip) ret;
    `ani~draw(
      `window=, `x + (float)(.com.GameWidth-320)/2.0,
      `y + (float)(.com.GameHeight-240), 1.0, 1.0,
      `xscl, `xscl, `yscl, 0.0, 0.0, .consts.null!&.com.PalFX?(), false); 
  }
  public void setPos(float x, float y)
  {
    `x = x;
    `y = y;
  }
  public void addPos(float x, float y)
  {
    `x += x;
    `y += y;
  }
  public void setScale(float x, float y)
  {
    `xscl = x;
    `yscl = y;
  }
  public void setTile(int x, int y)
  {
    `ani~tile.w = x;
    `ani~tile.h = y;
  }
  public void setColorKey(int ck)
  {
    `ani~mask = ck;
  }
  public void setAlpha(short sa, short da)
  {
    `ani~salpha = sa;
    `ani~dalpha = da;
  }
  public void setWindow(float x, float y, float w, float h)
  {
    `window.x = (int)((x+(float)(.com.GameWidth-320)/2.0)*.com.WidthScale);
    `window.y = (int)((y+(float)(.com.GameHeight-240))*.com.HeightScale);
    `window.w = (int)(w * .com.WidthScale + 0.5);
    `window.h = (int)(h * .com.HeightScale + 0.5);
  }
}
void animNew(&.lua.State L=, int re=)
{
  int argc = 0, nret = 1;
  ^&.Anim anim.new(1);
  ^&.sc.Sff sff = .sc.refArg!&.sc.Sff?(L=, re=, argc=, nret); if(re < 0) ret;
  ^/char action = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~setSff(sff~getSff());
  if(!anim~setAction(action)){
    L.pushString(
      \r\n + action[0..4096] + \r\n\r\n"データの読み込みに失敗しました。");
    re = -1;
    ret;
  }
  L.pushRef(anim);
}
void animSetPos(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~setPos(x, y);
}
void animAddPos(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~addPos(x, y);
}
void animSetTile(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  int x = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int y = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~setTile(x, y);
}
void animSetColorKey(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  int ck = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~setColorKey(ck);
}
void animSetAlpha(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  int x = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int y = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~setAlpha(x, y);
}
void animSetScale(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~setScale(x, y);
}
void animSetWindow(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float w = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float h = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  anim~setWindow(x, y, w, h);
}
void animUpdate(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  anim~update();
}
void animDraw(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.Anim anim = .sc.refArg!&.Anim?(L=, re=, argc=, nret); if(re < 0) ret;
  anim~draw();
}


void enterNetPlay(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^/char host = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  if(#.cmd.net > 0){
    L.pushString("すでに通信中です。");
    re = -1;
    ret;
  }
  .chr.chars.new(#.chr.chars);
  .cmd.net.new(1);
  .cmd.net~openReplayFile("replay/netplay.replay");
  branch{
  cond #host > 0:
    .cmd.net~connect(host, .listenPort);
  else:
    .cmd.net~accept(.listenPort);
  }
}

void exitNetPlay(&.lua.State L=, int re=)
{
  re = 0;
  .cmd.net.new(0);
}

void enterReplay(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^/char file = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  .chr.chars.new(#.chr.chars);
  .cmd.replay.new(1);
  .cmd.replay~open(file);
}

void exitReplay(&.lua.State L=, int re=)
{
  re = 0;
  .cmd.replay.new(0);
}

void setCom(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  int pn = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  if(!.m.inRange!int?(1, #.chr.chars, pn)){
    L.pushString("プレイヤー番号が不正です。");
    re = -1;
    ret;
  }
  int ai = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .m.limMin!int?(ai=, 0);
  .com.com[pn-1] = ai;
}

void setAutoLevel(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  bool b = .sc.blArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.autolevel = b;
}

void getListenPort(&.lua.State L=, int re=)
{
  re = 1;
  L.pushString(.listenPort);
}

void connected(&.lua.State L=, int re=)
{
  re = 1;
  L.pushBoolean(#.cmd.net > 0 && .cmd.net~isConnected());
}

void setListenPort(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^/char port = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  if(#port > 0) .listenPort = port;
}

void synchronize(&.lua.State L=, int re=)
{
  re = 0;
  if(!.cmd.synchronize()){
    L.pushString("同期エラーです。");
    re = -1;
    ret;
  }
}

void addChar(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^^/char lines = .s.splitLines(.sc.strArg(L=, re=, argc=, nret));
  if(re < 0) ret;
  loop{index i = 0; while; do:
    .syst.selinf.sel.addChar(lines[i]);
    i++;
  while i < #lines:}
}

void addStage(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^^/char lines = .s.splitLines(.sc.strArg(L=, re=, argc=, nret));
  if(re < 0) ret;
  loop{index i = 0; while; do:
    .syst.selinf.sel.addStage(lines[i]);
    i++;
  while i < #lines:}
}

void setRandomSpr(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^&.sc.Sff sff = .sc.refArg!&.sc.Sff?(L=, re=, argc=, nret); if(re < 0) ret;
  int g = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int n = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float xs = .syst.selinf.sel.randxscl, ys = .syst.selinf.sel.randyscl;
  if(L.getTop() > argc){
    xs = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  }
  if(L.getTop() > argc){
    ys = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  }
  ^&.sff.Sff sf = sff~getSff();
  if(#sf > 0) .syst.selinf.sel.randomspr = sf~getOwnPalSprite(g, n);
  .syst.selinf.sel.randxscl = xs;
  .syst.selinf.sel.randyscl = ys;
}

void setSelColRow(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  int c = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int r = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .syst.selinf.sel.columns = c;
  .syst.selinf.sel.rows = r;
}

void setSelCellSize(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .syst.selinf.sel.cellsizex = x;
  .syst.selinf.sel.cellsizey = y;
}

void setSelCellScale(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .syst.selinf.sel.cellscalex = x;
  .syst.selinf.sel.cellscaley = y;
}

void numSelCells(&.lua.State L=, int re=)
{
  re = 1;
  L.pushNumber((double)#.syst.selinf.sel.charlist);
}

void setStage(&.lua.State L=, int re=)
{
  int argc = 0, nret = 1;
  int n = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  L.pushNumber((double).syst.selinf.sel.setStageNo(n));
}

void selectStage(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  int n = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .syst.selinf.sel.selectStage(n);
}

void setTeamMode(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  int pn = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  if(!.m.inRange!int?(1, 2, pn)){
    L.pushString("チーム番号が不正です。");
    re = -1;
    ret;
  }
  int tm = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  if(!.m.inRange!int?(0, 2, tm)){
    L.pushString("モード番号が不正です。");
    re = -1;
    ret;
  }
  int nt = 1;
  if(tm >= 1){
    nt = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
    if(!.m.inRange!int?(1, 10, nt)){
      L.pushString("チーム人数が不正です。");
      re = -1;
      ret;
    }
  }
  .syst.selinf.p[pn-1].selchr.new(0);
  .com.tmode[pn-1] = tm;
  .com.numturns[pn-1] = .com.numSimul[pn-1] = nt;
  if(tm == 1 && nt == 1) .com.tmode[pn-1] = 0;
}

void getCharName(&.lua.State L=, int re=)
{
  int argc = 0, nret = 1;
  int n = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  ^&.sys.Select::Char c = .syst.selinf.sel.getChar(n);
  L.pushString(#c > 0 ? c~name : "");
}

void getCharFileName(&.lua.State L=, int re=)
{
  int argc = 0, nret = 1;
  int n = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  ^&.sys.Select::Char c = .syst.selinf.sel.getChar(n);
  L.pushString(#c > 0 ? c~def : "");
}

void selectChar(&.lua.State L=, int re=)
{
  int argc = 0, nret = 1;
  int pn = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  if(!.m.inRange!int?(1, 2, pn)){
    L.pushString("チーム番号が不正です。");
    re = -1;
    ret;
  }
  int cn = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int pl = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int retval = 0;
  if(.m.inRange!int?(1, 12, pl) && .syst.selinf.addSelchr(pn-1, cn, pl)){
    switch(.com.tmode[pn-1]){
    case (int).com.TeamMode::Single:
      retval = 2;
    case (int).com.TeamMode::Simul:
      retval = #.syst.selinf.p[pn-1].selchr >= .com.numSimul[pn-1] ? 2 : 1;
    case (int).com.TeamMode::Turns:
      retval = #.syst.selinf.p[pn-1].selchr >= .com.numturns[pn-1] ? 2 : 1;
    }
  }
  L.pushNumber((double)retval);
}

void getStageName(&.lua.State L=, int re=)
{
  int argc = 0, nret = 1;
  int n = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  L.pushString(.syst.selinf.sel.getStageName(n));
}

void refresh(&.lua.State L=, int re=)
{
  re = 0;
  if(!.se.fskip){
  /?/*.cfg.OpenGL:
    .sdl.GlSwapBuffers(::);
  /*true:
    .sdl.flip();
    .com.screenFill(0x00000000);
  /*?*/
  }
  .snd.playSound();
  if(!.cmd.update()) .se.end = true;
  if(.se.end){
    L.pushString("<game end>");
    re = -1;
  }
}

void drawPortrait(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  index n = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float xscl = 1.0, yscl = 1.0;
  if(L.getTop() > argc){
    xscl = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  }
  if(L.getTop() > argc){
    yscl = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  }
  if(!.se.fskip){
    ^&.sys.Select::Char c = .syst.selinf.sel.getChar(n);
    if(#c > 0 && #c~lportrait > 0){
      c~lportrait~draw(x, y, xscl, yscl, c~lportrait~colorPallet);
    }
  }
}

void drawFace(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float x = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  float y = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int offset = 0;
  if(L.getTop() > argc){
    offset = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  }
  if(!.se.fskip) loop{
    int j = 0;
    ^&.sys.Select::Char c;
    while;
  do:
    loop{int i = 0; while; do:
      c = .syst.selinf.sel.getChar(offset++);
      if(#c > 0) branch{
      cond #c~sportrait > 0:
        c~sportrait~draw(
          x + (float)i*.syst.selinf.sel.cellsizex,
          y + (float)j*.syst.selinf.sel.cellsizey,
          .syst.selinf.sel.cellscalex, .syst.selinf.sel.cellscaley,
          c~sportrait~colorPallet);
      cond .s.equ(c~def, "randomselect") && #.syst.selinf.sel.randomspr > 0:
        .syst.selinf.sel.randomspr~draw(
          x + (float)i*.syst.selinf.sel.cellsizex,
          y + (float)j*.syst.selinf.sel.cellsizey,
          .syst.selinf.sel.randxscl, .syst.selinf.sel.randxscl,
          .syst.selinf.sel.randomspr~colorPallet);
      }
      i++;
    while i < .syst.selinf.sel.columns:}
    j++;
  while j < .syst.selinf.sel.rows:}
}

void loadLifebar(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^/char lifebar = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  .syst.fig.new(1);
  ^/char error;
  if(#.syst.fig~load(lifebar)=>error > 0){
    L.pushString(error);
    re = -1;
    ret;
  }
}

void loadDebugFont(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^/char font = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  .fnt.debugFont.new(1);
  .fnt.debugFont~loadFile(font);
}

void setDebugScript(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  ^/char dscript = .sc.strArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.debugScript = dscript;
}

void setLifeMul(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float l = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.life = l;
}

void setTeam1VS2Life(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float t12 = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.team1VS2Life = t12;
}

void setTurnsRecoveryRate(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float tr = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.turnsRecoveryRate = tr;
}

void setZoom(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  bool z = .sc.blArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.cam.zoom = z;
}

void setZoomMin(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float zmi = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.cam.zoomMin = zmi;
}

void setZoomMax(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float zma = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.cam.zoomMax = zma;
}

void setZoomSpeed(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  float zs = .sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.cam.zoomSpeed = 12.0 - zs;
}

void resetRemapInput(&.lua.State L=, int re=)
{
  re = 0;
  .com.resetRemapInput();
}

void remapInput(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  int src = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  int dest = (int).sc.numArg(L=, re=, argc=, nret); if(re < 0) ret;
  if(
    !.m.inRange!int?(1, #.com.inputRemap, src)
    || !.m.inRange!int?(1, #.com.inputRemap, dest))
  {
    L.pushString("プレイヤー番号が不正です。");
    re = -1;
    ret;
  }
  .com.inputRemap[src-1] = dest-1;
}

void setSharedLife(&.lua.State L=, int re=)
{
  int argc = 0, nret = 0;
  bool b = .sc.blArg(L=, re=, argc=, nret); if(re < 0) ret;
  .com.sharedLife = b;
}

public void init(&.lua.State L=)
{
  .sc.init(L=);
  L.register("textImgNew", .textImgNew);
  L.register("textImgSetFont", .textImgSetFont);
  L.register("textImgSetBank", .textImgSetBank);
  L.register("textImgSetAlign", .textImgSetAlign);
  L.register("textImgSetText", .textImgSetText);
  L.register("textImgSetPos", .textImgSetPos);
  L.register("textImgSetScale", .textImgSetScale);
  L.register("textImgDraw", .textImgDraw);
  L.register("animNew", .animNew);
  L.register("animSetPos", .animSetPos);
  L.register("animAddPos", .animAddPos);
  L.register("animSetTile", .animSetTile);
  L.register("animSetColorKey", .animSetColorKey);
  L.register("animSetAlpha", .animSetAlpha);
  L.register("animSetScale", .animSetScale);
  L.register("animSetWindow", .animSetWindow);
  L.register("animUpdate", .animUpdate);
  L.register("animDraw", .animDraw);
  L.register("enterNetPlay", .enterNetPlay);
  L.register("exitNetPlay", .exitNetPlay);
  L.register("enterReplay", .enterReplay);
  L.register("exitReplay", .exitReplay);
  L.register("setCom", .setCom);
  L.register("setAutoLevel", .setAutoLevel);
  L.register("getListenPort", .getListenPort);
  L.register("setListenPort", .setListenPort);
  L.register("connected", .connected);
  L.register("synchronize", .synchronize);
  L.register("addChar", .addChar);
  L.register("addStage", .addStage);
  L.register("setRandomSpr", .setRandomSpr);
  L.register("setSelColRow", .setSelColRow);
  L.register("setSelCellSize", .setSelCellSize);
  L.register("setSelCellScale", .setSelCellScale);
  L.register("numSelCells", .numSelCells);
  L.register("setStage", .setStage);
  L.register("selectStage", .selectStage);
  L.register("setTeamMode", .setTeamMode);
  L.register("getCharName", .getCharName);
  L.register("getCharFileName", .getCharFileName);
  L.register("selectChar", .selectChar);
  L.register("getStageName", .getStageName);
  L.register("refresh", .refresh);
  L.register("drawPortrait", .drawPortrait);
  L.register("drawFace", .drawFace);
  L.register("loadLifebar", .loadLifebar);
  L.register("loadDebugFont", .loadDebugFont);
  L.register("setDebugScript", .setDebugScript);
  L.register("setLifeMul", .setLifeMul);
  L.register("setTeam1VS2Life", .setTeam1VS2Life);
  L.register("setTurnsRecoveryRate", .setTurnsRecoveryRate);
  L.register("setZoom", .setZoom);
  L.register("setZoomMin", .setZoomMin);
  L.register("setZoomMax", .setZoomMax);
  L.register("setZoomSpeed", .setZoomSpeed);
  L.register("resetRemapInput", .resetRemapInput);
  L.register("remapInput", .remapInput);
  L.register("setSharedLife", .setSharedLife);
}


